package com.bac.rentmap.ad.flat.jdo;

import java.util.List;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.flat.FlatAd;
import com.bac.rentmap.ad.flat.SecureFlatAdNotFoundException;
import com.bac.rentmap.ad.flat.image.FlatImageService;
import com.bac.rentmap.ad.flat.security.jdo.JdoFlatDao;
import com.bac.rentmap.jdo.JdoSupport;

public class JdoFlatAdDaoImpl extends JdoSupport implements JdoFlatAdDao {
    private static final Logger log = Logger.getLogger(JdoFlatAdDao.class
            .getName());
    private JdoFlatDao flatDao;
    private FlatImageService flatImageService;

    public FlatAd find(String street, Integer building, String phone,
            PersistenceManager persistenceManager) {
        log.fine("Searching FlatAd by " + street + ", " + building + ", "
                + phone);
        try {
            Query query = persistenceManager.newQuery(FlatAd.class);
            query.setFilter("street == streetParam && building == buildingParam && phone == phoneParam");
            query.declareParameters("String streetParam, Integer buildingParam, String phoneParam");

            @SuppressWarnings("unchecked")
            List<FlatAd> flatAds = (List<FlatAd>) query.execute(street,
                    building, phone);
            if (flatAds.isEmpty())
                return null;
            if (flatAds.size() > 1)
                throw new IllegalArgumentException(
                        "More than one ad found for " + street + ", "
                                + building + ", " + phone + ", " + flatAds);
            return flatAds.iterator().next();
        } finally {
            // persistenceManager.close();
        }
    }

    public FlatAd get(Long flatAdId) {
        log.fine("Get FlatAd by id " + flatAdId);
        PersistenceManager persistenceManager = getPersistenceManager();
        FlatAd res = null;
        try {
             res = persistenceManager.getObjectById(FlatAd.class,
                    flatAdId);
             res.getFlatImages(); // load images
             res.getReviewers();
        } catch(JDOObjectNotFoundException ex){
            return null;
        }
        finally {
            persistenceManager.close();
        }
//        if(res != null){
//            log.fine("Images outside: " + res.getFlatImageIds());
//        }
        return res;
    }

    @Override
    public Long deleteBySecureId(String secureId) {
        PersistenceManager persistenceManager = getPersistenceManager();
        try{
            Long flatAdId = flatDao.deleteBySecureId(secureId, persistenceManager);
            if(flatAdId != null){
                flatImageService.deleteAll(flatAdId, persistenceManager);
            }
            return flatAdId;
        }finally{
            persistenceManager.close();
        }
    }

    @Override
    public FlatAd getBySecureId(String secureId) {
        return (FlatAd) flatDao.getBySecureId(FlatAd.class, secureId);
    }

    @Override
    public FlatAd loadBySecureId(String secureId,
            PersistenceManager persistenceManager)
            throws SecureFlatAdNotFoundException {
        return ensureNotNull((FlatAd) flatDao.getBySecureId(FlatAd.class,
                secureId, persistenceManager), secureId);
    }

    @Override
    public FlatAd loadBySecureId(String secureId)
            throws SecureFlatAdNotFoundException {
        return ensureNotNull((FlatAd) flatDao.getBySecureId(FlatAd.class,
                secureId), secureId);

    }

    private FlatAd ensureNotNull(FlatAd flatAd, String secureId) {
        if (flatAd == null) {
            throw new SecureFlatAdNotFoundException(secureId);
        }
        return flatAd;
    }

    @Required
    public void setFlatDao(JdoFlatDao flatDao) {
        this.flatDao = flatDao;
    }

    @Required
    public void setFlatImageService(FlatImageService flatImageService) {
        this.flatImageService = flatImageService;
    }

}
